package com.xxl.job.admin.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobTenant;
import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.core.util.TenantContextUtil;
import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.admin.dao.XxlJobTenantDao;
import com.xxl.job.admin.dao.XxlJobUserDao;
import com.xxl.job.core.biz.model.ReturnT;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

/**
 * @author chenlinqing
 * @description:
 * @date: 2025/7/28 16:07
 */
@Controller
@RequestMapping("/tenant")
public class JobTenantController {

    @Resource
    private XxlJobUserDao xxlJobUserDao;
    @Resource
    private XxlJobGroupDao xxlJobGroupDao;
    @Resource
    private XxlJobTenantDao xxlJobTenantDao;
    @Resource
    private XxlJobInfoDao xxlJobInfoDao;

    @RequestMapping
    @PermissionLimit(adminuser = true)
    public String index() {
        return "tenant/tenant.index";
    }

    @RequestMapping("/pageList")
    @ResponseBody
    @PermissionLimit(adminuser = true)
    public Map<String, Object> pageList(@RequestParam(value = "start", required = false, defaultValue = "1") int start,
                                        @RequestParam(value = "length", required = false, defaultValue = "10") int length,
                                        @RequestParam(value = "tenantId", required = false) String tenantId,
                                        @RequestParam(value = "tenantName", required = false) String tenantName,
                                        @RequestParam(value = "validStatus", required = false) String validStatus) {

        Page<XxlJobTenant> page = new Page<>(start, length);
        LambdaQueryWrapper<XxlJobTenant> queryWrapper = Wrappers.lambdaQuery(XxlJobTenant.class)
                .like(StringUtils.hasText(tenantId), XxlJobTenant::getTenantId, tenantId)
                .like(StringUtils.hasText(tenantName), XxlJobTenant::getTenantName, tenantName)
                .eq(StringUtils.hasText(validStatus), XxlJobTenant::getValidStatus, validStatus);
        Page<XxlJobTenant> result = xxlJobTenantDao.selectPage(page, queryWrapper);
        // package result
        Map<String, Object> maps = new HashMap<String, Object>();
        // 总记录数
        maps.put("recordsTotal", result.getTotal());
        // 过滤后的总记录数
        maps.put("recordsFiltered", result.getRecords().size());
        // 分页列表
        maps.put("data", result.getRecords());
        return maps;
    }

    /**
     * @param xxlJobTenant
     * @return
     */
    @RequestMapping("/add")
    @ResponseBody
    @PermissionLimit(adminuser = true)
    @Transactional(rollbackFor = Exception.class)
    public ReturnT<String> add(XxlJobTenant xxlJobTenant) {
        if (!"admin".equals(TenantContextUtil.getTenantId())) {
            return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_permission_limit"));
        }
        if (!StringUtils.hasText(xxlJobTenant.getTenantId())) {
            return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_please_input") + I18nUtil.getString("tenant_id"));
        }
        if (!StringUtils.hasText(xxlJobTenant.getTenantName())) {
            return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_please_input") + I18nUtil.getString("tenant_name"));
        }
        XxlJobTenant oldRecord = xxlJobTenantDao.selectById(xxlJobTenant.getTenantId());
        if (oldRecord != null) {
            return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("tenant_exist_error"));
        }

        if (!StringUtils.hasText(xxlJobTenant.getAdminPassword())) {
            xxlJobTenant.setAdminPassword("123456");
        }
        TenantContextUtil.setTenantId(xxlJobTenant.getTenantId());
        //添加租户
        xxlJobTenantDao.insert(xxlJobTenant);
        //添加管理员
        XxlJobUser xxlJobUser = new XxlJobUser();
        xxlJobUser.setUsername("admin");
        xxlJobUser.setPassword(DigestUtils.md5DigestAsHex(xxlJobTenant.getAdminPassword().getBytes()));
        xxlJobUser.setRole(1);
        xxlJobUserDao.save(xxlJobUser);

        //添加默认执行器
        XxlJobGroup jobGroup = new XxlJobGroup();
        jobGroup.setAppname("xxl-job-executor-sample");
        jobGroup.setTitle("通用执行器Sample");
        jobGroup.setAddressType(0);
        xxlJobGroupDao.save(jobGroup);

        return ReturnT.SUCCESS;
    }

    /**
     * 更新租户信息。除了表的数据，还要包括租户管理员的密码。租户有效状态。不支持删除租户。主要是考虑到租户下面可能已有执行器。
     * 当租户无效时，需要将这个租户下面的所有定时任务都停止。
     *
     * @param request
     * @param xxlJobTenant
     * @return
     */
    @RequestMapping("/update")
    @ResponseBody
    @PermissionLimit(adminuser = true)
    @Transactional(rollbackFor = Exception.class)
    public ReturnT<String> update(HttpServletRequest request, XxlJobTenant xxlJobTenant) {
        if (!"admin".equals(TenantContextUtil.getTenantId())) {
            return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_permission_limit"));
        }

        if("admin".equals(xxlJobTenant.getTenantId()) && "N".equals(xxlJobTenant.getValidStatus())){
            return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("tenant_can_not_set_invalid"));
        }

        if (!StringUtils.hasText(xxlJobTenant.getTenantId())) {
            return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_please_input") + I18nUtil.getString("tenant_id"));
        }

        TenantContextUtil.setTenantId(xxlJobTenant.getTenantId());
        xxlJobTenantDao.updateById(xxlJobTenant);

        // 更新密码
        if (StringUtils.hasText(xxlJobTenant.getAdminPassword())) {
            xxlJobTenant.setAdminPassword(xxlJobTenant.getAdminPassword().trim());
            if (!(xxlJobTenant.getAdminPassword().length() >= 4 && xxlJobTenant.getAdminPassword().length() <= 20)) {
                return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit") + "[4-20]");
            }
            // md5 password
            XxlJobUser xxlJobUser = new XxlJobUser();
            xxlJobUser.setTenantId(xxlJobTenant.getTenantId());
            xxlJobUser.setUsername("admin");
            xxlJobUser.setPassword(DigestUtils.md5DigestAsHex(xxlJobTenant.getAdminPassword().getBytes()));
            xxlJobUserDao.updatePassword(xxlJobUser);
        }
        //如果状态是无效，要将租户下面所有定时任务停止
        if ("N".equals(xxlJobTenant.getValidStatus())) {
            xxlJobInfoDao.stopAllJob();
        }
        return ReturnT.SUCCESS;
    }
}
